package org.wupuser.service.impl;

import jakarta.annotation.Resource;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.orm.jpa.JpaSystemException;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.wupuser.model.User;
import org.wupuser.model.dto.LoginRespDTO;
import org.wupuser.model.dto.UpdateUserRequest;
import org.wupuser.repository.BannerRepository;
import org.wupuser.repository.UserRepository;
import org.wupuser.service.UserService;
import org.wupuser.util.JWTTokenUtil;
import org.wupuser.util.JedisUtils;
import org.wupuser.util.ValidateFileTypeUtil;
import redis.clients.jedis.exceptions.JedisException;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Instant;

@Service
public class UserServiceImpl implements UserService {
	@Resource
	private UserRepository userRepository;
	@Resource
	private BannerRepository bannerRepository;
	
	/**
	 * 根据邮箱地址加载用户信息
	 *
	 * @param email 用户的邮箱地址，用于查询用户
	 *
	 * @return 返回找到的用户对象，如果未找到则返回null
	 */
	@Override
	public User loadUser(
		String email) { // 参数：用户的邮箱地址
		
		// 如果用户不存在，返回null
		return userRepository.findByEmail(email); // 返回找到的用户对象
	}
	
	
	/**
	 * 用户登录方法
	 *
	 * @param email    用户邮箱
	 * @param password 用户密码
	 *
	 * @return LoginRequest 登录请求响应对象，包含登录状态、消息和数据
	 */
	@Override
	public LoginRespDTO login(
		String email,
		// 用户邮箱
		String password) {    // 用户密码
		// 根据邮箱加载用户信息
		User user = loadUser(email);
		// 创建登录请求响应对象
		LoginRespDTO loginRespDTO = new LoginRespDTO();
		// 判断用户是否存在
		if (user == null) {
			// 用户不存在，设置错误消息并返回
			loginRespDTO.setMessage("用户不存在");
			return loginRespDTO;
		}
		// 验证用户密码是否正确
		if (! user
			.getPassword()
			.equals(password)) {
			// 密码错误，设置错误消息并返回
			loginRespDTO.setMessage("密码错误");
			return loginRespDTO;
		} else {
			// 检查用户是否被封禁
			if (bannerRepository.findByUuid(user.getId()) == null) {
				
				// 用户未被封禁，登录成功
				loginRespDTO.setData(user);    // 设置用户数据
				loginRespDTO.setMessage("登录成功");    // 设置成功消息
				// 生成JWT令牌
				String token = JWTTokenUtil.getToken(String.valueOf(user.getId()));
				// 将令牌存储到Redis中
				JedisUtils.set(
					String.valueOf(user.getId()),
					token);
				// 设置令牌到响应对象中
				loginRespDTO.setToken(token);
				return loginRespDTO;
			}
		}
		// 用户被封禁，设置错误消息并返回
		loginRespDTO.setMessage("该用户已被封禁！");
		return loginRespDTO;
	}
	
	/**
	 * 用户注册方法
	 *
	 * @param user 包含用户注册信息的User对象
	 *
	 * @return 返回注册结果信息字符串
	 */
	@Override
	public String reg(User user) {
		user.setCreateTime(Instant.now());
		user.setUpdateTime(Instant.now());
		user.setDeleted(false);
		try {
			// 尝试保存用户信息
			userRepository.saveUser(user);
		}
		catch (DataIntegrityViolationException e) {
			// 捕获数据完整性异常，说明用户名或邮箱已存在
			return "用户名或邮箱已存在";
		}
		catch (JpaSystemException e) {
			// 捕获JPA系统异常，说明数据库操作失败
			return "系统错误，注册失败";
		}
		catch (Exception e) {
			// 捕获异常并返回注册失败信息
			return "未知错误，注册失败";
		}
		// 注册成功返回成功信息
		return "注册成功";
	}
	
	/**
	 * 更新用户信息的公共方法
	 *
	 * @param updateUserRequest 包含更新类型和用户信息的请求对象
	 *
	 * @return 返回操作结果字符串，如"修改成功"、"密码相同"等
	 */
	@Override
	public String updateUser(UpdateUserRequest updateUserRequest) {
		// 获取更新类型标识
		String key = updateUserRequest.getKey();
		// 设置用户更新时间为当前时间
		updateUserRequest
			.getUser()
			.setUpdateTime(Instant.now());
		// 根据ID查询用户
		User user = userRepository.findUserById(updateUserRequest
			                                        .getUser()
			                                        .getId());
		// 根据不同的更新类型执行不同的更新逻辑
		switch (key) {
			case "password":
				if (! updateUserRequest
					.getOldPassword()
					.equals(user.getPassword())) {
					return "输入的原密码不正确";
				}
				// 检查新密码是否与旧密码相同
				if (user
					.getPassword()
					.equals(updateUserRequest
						        .getUser()
						        .getPassword())) {
					return "密码相同";
				}
				try {
					// 更新用户密码
					userRepository.updatePassword(updateUserRequest.getUser());
				}
				catch (Exception e) {
					return "修改失败";
				}
				return "修改成功";
			case "email":
				if (user
					.getEmail()
					.equals(updateUserRequest
						        .getUser()
						        .getEmail())) {
					return "邮箱未更改";
				}
				try {
					// 更新用户邮箱
					userRepository.updateEmail(updateUserRequest.getUser());
				}
				catch (DataIntegrityViolationException e) {
					// 捕获数据完整性异常，说明邮箱已被占用
					return "邮箱已被占用";
				}
				catch (JpaSystemException e) {
					// 捕获JPA系统异常，说明数据库操作失败
					return "系统错误，修改失败";
				}
				catch (Exception e) {
					return "未知错误，修改失败";
				}
				return "修改成功";
			case "username":
				if (user
					.getUsername()
					.equals(updateUserRequest
						        .getUser()
						        .getUsername())) {
					return "用户名未更改";
				}
				try {
					// 更新用户名
					userRepository.updateUsername(updateUserRequest.getUser());
				}
				catch (DataIntegrityViolationException e) {
					// 捕获数据完整性异常，说明用户名已被占用
					return "用户名已被占用";
				}
				catch (JpaSystemException e) {
					// 捕获JPA系统异常，说明数据库操作失败
					return "系统错误，修改失败";
				}
				catch (Exception e) {
					return "未知错误，修改失败";
				}
				return "修改成功";
			case "signatrue":
				// 检查用户信息是否有变更
				if (user
					.getSignatrue()
					.equals(updateUserRequest
						        .getUser()
						        .getSignatrue())) {
					return "签名未更改";
				}
				try {
					// 更新用户信息
					userRepository.updateInfo(updateUserRequest.getUser());
				}
				catch (JpaSystemException e) {
					// 捕获JPA系统异常，说明数据库操作失败
					return "系统错误，修改失败";
				}
				catch (Exception e) {
					return "修改失败";
				}
				return "修改成功";
		}
		// 如果没有匹配的更新类型，返回无修改提示
		return "无修改";
	}
	
	/**
	 * 更新用户头像的方法
	 *
	 * @param file  用户上传的头像文件
	 * @param email 用户的邮箱地址
	 *
	 * @return 返回操作结果信息，包括成功或失败原因
	 */
	@Override
	public String userAvatarUpdate(
		MultipartFile file,
		// 用户上传的头像文件
		String email) {       // 用户的邮箱地址，用于识别用户
		// 检查上传文件是否为空
		if (file == null) {
			return "头像为空";
		}
		// 根据邮箱加载用户信息
		User user = loadUser(email);
		// 更新用户信息修改时间
		user.setUpdateTime(Instant.now());
		try {
			// 验证文件类型是否合法
			if (! ValidateFileTypeUtil.validateFileType(file)) {
				return "头像类型不合法";
			} else if (file.getSize() > 1024 * 1024 * 2) {
				return "头像大小超过限制";
			}
			
			String source = System.getProperty("user.dir") + File.separator + "data" + File.separator + "avatar" + File.separator;
			String fileExtension = file
				.getOriginalFilename()
				.substring(file
					           .getOriginalFilename()
					           .lastIndexOf("."));
			String fileName = user.getId() + fileExtension;
			
			Path savePath = Path.of(source + fileName);
			if (! Files.exists(Path.of(source))) {
				Files.createDirectory(Path.of(source));
			} else if (Files.exists(savePath)) {
				Files.delete(savePath);
			}
			file.transferTo(savePath);
			user.setAvatar(fileName);
			userRepository.updateAvatar(user);
		}
		catch (IOException e) {
			return "文件读取失败";
		}
		catch (IllegalStateException e) {
			return "状态非法";
		}
		catch (NullPointerException e) {
			return "文件名非法，请确保文件拥有后缀名";
		}
		catch (JpaSystemException e) {
			return "保存至数据库失败";
		}
		catch (Exception e) {
			return "未知错误，修改失败";
		}
		return "修改成功";
	}
	
	/**
	 * 用户退出方法
	 *
	 * @param email 用户的邮箱地址，用于标识需要退出的用户
	 *
	 * @return 返回操作结果信息，如"退出成功"或提示Redis中不存在该用户的Token
	 */
	@Override
	public String exit(String email) {
		// 根据邮箱加载用户信息
		User user = loadUser(email);
		try {
			// 尝试从Redis中删除该用户的Token
			JedisUtils.del(String.valueOf(user.getId()));
		}
		catch (JedisException e) {
			// 如果捕获到异常，说明Redis中不存在该用户的Token
			return "Redis中不存在该用户的Token，实际已退出";
		}
		// 正常退出成功的情况
		return "退出成功";
	}
}
